﻿// Copyright (c) 2010 Dan Popick

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

using Open.Web.Stijl;
using Open.Web.Stijl.Utility;

namespace StijlBilder
{
	/// <summary>
	/// Task-speciic behavior for the tiling engine
	/// </summary>
	/// <remarks>
	/// The task engine places all the CSS files in a subdirectory named after the CSS file itself.
	/// 
	/// </remarks>
	class TaskTileEngine: TileEngine
	{
		Open.Web.Stijl.Utility.Tracer<TileEngine> _log = new Open.Web.Stijl.Utility.Tracer<TileEngine>();
		Open.Web.Stijl.Configuration.StijlConfiguration _config = Open.Web.Stijl.Configuration.StijlConfiguration.Default;

		public string CssFileName { get; private set; }
		public string RootPath { get; private set; }

		public TaskTileEngine()
		{
		}

		/// <summary>
		/// GenerateImage sets the filename for each image using the abstract GenerateUrl method
		/// and generates the image data.
		/// </summary>
		/// <param name="images">The list of images on which to act.</param>
		/// <remarks>
		/// Task-based engine needs to add the image CRCs to the total CRC
		/// so we can tag the CSS file and output directry with the (pseudo-)unique
		/// hash before generating the new background-image URLs. 
		/// 
		/// Without adding the image data into the CRC in the directory,
		/// updates to the image set will not cause the CRC to change and
		/// the output of the build task will be placed in the same output
		/// directory so long as the CSS file doesn't change.
		/// </remarks>
		protected override void GenerateImages(List<TiledImage> images)
		{
			// compute the hash for the input CSS file (we can't use
			// the output CSS for this; since the re-written rulesets
			// include the hash as part of the filename, it is impossible
			// to get the two to agree.
			Crc32 crcHasher = new Crc32();
			crcHasher.ComputeHash(File.ReadAllBytes(InputCssPath));

			// generate the images and set the names, compute the hash, too
			images.ForEach(x =>
				{
					x.GenerateImage();
					crcHasher.ComputeHash(x.ImageData);
				});
			uint crcValue = crcHasher.CrcValue;

			// save CSS file
			CssFileName = Path.GetFileName(InputCssPath);
			RootPath = String.Format(_config.OutputDirectoryFormat,
					Path.GetFileNameWithoutExtension(InputCssPath).TrimEnd('.'),
					DateTime.Now,
					crcValue);

			_log.Info("Output path for '{0}' is '{1}'",
				InputCssPath,
				CssFileName);

			int index = 0;
			images.ForEach(x => 
				{
					string imPath = GenerateUrl(index++, x);
					_log.Info("Image targeted for '{0}'", imPath);
					x.SetFilename(imPath);
				});
		}

		/// <summary>
		/// Generates the URL for the image. Must be overridden based on the context (handler/task)
		/// </summary>
		/// <param name="imageIndex">An index for the image, unique for each CSS file.</param>
		/// <param name="image">The tiled image reference.</param>
		/// <returns>The path to the image to be rendered out to the updated CSS file</returns>
		/// <remarks>
		/// Overridden here to place the output tiled images into a subdirectory named after
		/// the CSS file, minus the extension.
		/// </remarks>
		protected override string GenerateUrl(int imageIndex, TiledImage image)
		{
			return String.Format(@"{0}\{1}.png", RootPath, imageIndex);
		}
	}
}
